package com.my.mycommoncore.utils;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.my.mycommondomain.constants.CommonConstants;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class JsonUtils {

    public  static ObjectMapper OBJECT_MAPPER ;
    static {
        OBJECT_MAPPER =
                JsonMapper.builder().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                        .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                        .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
                        .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
                        .configure(MapperFeature.USE_ANNOTATIONS, false)
                        .addModule(new JavaTimeModule())
                        .addModule(new SimpleModule()
                                .addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
                                .addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
                        )
                        .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
                        .serializationInclusion(JsonInclude.Include.NON_NULL)
                        .build();
    }

    /**
     * 对象转字符串
     * @param obj  传入得对象
     * @return  返回转换后的对象
     * @param <T>  泛型
     */
    public static <T> String objToString(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.warn("Parse Object to String error : {}",e.getMessage());
            return null;
        }
    }

    /**
     *
     * @param obj 传入的对象
     * @return   返回转后的json
     * @param <T>  泛型
     */
    public static <T> String objToStringPretty(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String) obj:OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.warn("Parse Object to String error1 : {}",e.getMessage());
            return null;
        }
    }

    /**
     * 字符串转对象
     * @param str 目标字符串
     * @param obj  要转成的对象
     * @return 返回
     * @param <T> 泛型
     */
    public static<T> T stringToObj(String str,Class<T> obj){
        //todo str==null||str.isEmpty() 提出到工具类
        if(str==null||str.isEmpty()||obj==null){
            return null;
        }
        try {
            return obj.equals(String.class) ? (T) str:OBJECT_MAPPER.readValue(str,obj);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error2 : {}",e.getMessage());
            return null;
        }
    }

    /**
     * 解决泛型嵌套问题
     * @param str 传入的字符串
     * @param valueType  具体的对象
     * @return   返回的对象
     * @param <T> 泛型
     */
    public static <T> T stringToObj(String str, TypeReference<T> valueType){
        if(str==null||str.isEmpty()||valueType==null){
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(str,valueType);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error3 : {}",e.getMessage());
            return null;
        }
    }

    /**
     * 泛型擦除
     * @param str   要转换的字符串
     * @param obj    具体的对象
     * @return      数组
     * @param <T>  obj
     */
    public  static <T> List<T> stringToList(String str,Class<T> obj){
        if(str==null||str.isEmpty()||obj==null){
            return null;
        }
        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(List.class, obj);
        try {
            return OBJECT_MAPPER.readValue(str,javaType);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error4 : {}",e.getMessage());
            return null;
        }
    }

    public static <T> Map<String,T> stringToMap(String str, Class<T> obj){
        if(str==null||str.isEmpty()||obj==null){
            return null;
        }
        JavaType mapType = OBJECT_MAPPER.getTypeFactory().constructMapType(LinkedHashMap.class, String.class, obj);
        try {
            return OBJECT_MAPPER.readValue(str,mapType);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error5 : {}",e.getMessage());
            return null;
        }

    }
}
